package vacuum.noxray;


import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockFadeEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockGrowEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerTeleportEvent;

public class Listener implements org.bukkit.event.Listener{

	private UpdateThread update = new UpdateThread();
	private boolean verbose;
	private boolean isActuallyOpaque = false;

	public Listener(){
		update.start();
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onPlayerMove(PlayerMoveEvent evt){
		if	(
				evt.getFrom().getBlockX() != evt.getTo().getBlockX()
				|| evt.getFrom().getBlockY() != evt.getTo().getBlockY()
				|| evt.getFrom().getBlockZ() != evt.getTo().getBlockZ()
				)
			updateVision(evt.getPlayer());
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onPlayerJoin(PlayerJoinEvent evt){
		if(verbose)
			System.out.println("Registering player " + evt.getPlayer().getName());
		PlayerVision.registerPlayer(evt.getPlayer(), verbose, isActuallyOpaque);
		updateVision(evt.getPlayer());
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onPlayerTeleport(PlayerTeleportEvent evt){
		PlayerVision.dumpPlayerCache(evt.getPlayer(), verbose);
		updateVision(evt.getPlayer());
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onPlayerQuit(PlayerQuitEvent evt){
		if(verbose)
			System.out.println("Unregistering player " + evt.getPlayer().getName());
		PlayerVision.unregisterPlayer(evt.getPlayer());
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockBreakEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockBurnEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockFadeEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockFromToEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockGrowEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockPhysicsEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockPistonExtendEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	@EventHandler(priority=EventPriority.MONITOR)
	public void onBlockEvent(BlockPistonRetractEvent evt){
		for(Player p : evt.getBlock().getWorld().getPlayers()){
			if(PlayerVision.isInCube(p, evt.getBlock().getLocation()))
				updateVision(p);
		}
	}

	private void updateVision(final Player p){
		if(p.hasPermission("vacuum.noxray.hide") && !update.players.contains(p))
			update.players.push(p);
	}

	public void killThread(){
		update.run = false;
	}

	public void setVerbose(boolean verbose) {
		this.verbose = verbose;
		update.verbose = verbose;
	}
	
	public void setIsActuallyOpaque(boolean isActuallyOpaque){
		this.isActuallyOpaque = isActuallyOpaque;
		if(isActuallyOpaque)
			update.isActuallyOpaque = true;
	}
}
